Extract Apical progenitors and compute Pseudo-DorsoVentral score

Extract apical progenitors and filter the gene expression matrix

We perform Kmeans clustering on the 2 cell state scores :

  • Apical progenitors AP
  • Basal progenitors BP

We then extract the glutamatergic neuron branche as beeing the Kmeans cluster with the highest mean Apical progenitor signature

Import Spring dimensionality reduction

Cell cycle associated genes were excluded for PCA dimensionality reduction and Spring plot was generating with these parameter :

Number of cells: 1648
Number of genes that passed filter: 857
Min expressing cells (gene filtering): 3
Min number of UMIs (gene filtering): 3
Gene variability %ile (gene filtering): 90
Number of principal components: 7
Number of nearest neighbors: 20
Number of force layout iterations: 500

Fit a principal curve over the AP in the Spring space

## Starting curve---distance^2: 2022449778
## Iteration 1---distance^2: 745172
## Iteration 2---distance^2: 696270.5
## Iteration 3---distance^2: 677509.1
## Iteration 4---distance^2: 668251.7
## Iteration 5---distance^2: 663393.6
## Iteration 6---distance^2: 660928.6
## Iteration 7---distance^2: 659586.4
## Iteration 8---distance^2: 658917.8
## Iteration 9---distance^2: 658638.8

Manuscript Fig. 5A

Manuscript Fig. 5A

Find differentially expressed genes along the pseudo DV axis

Cluster gene by similar profiles over pseudo-DV axis

Assign domain identity

We assign domain identity based on clusters’ transcriptional profile by setting boundaries over pseudo-dv score

Manuscript Fig. 5D

Manuscript Fig. 5D

Transfert these ident on the full dataset (Manuscript Fig. 2A)

## [1] "Cluster_Sub.Pallium.2: 363 Cells"
## [1] "Cluster_Ventral.Pallium: 312 Cells"
## [1] "Cluster_Sub.Pallium.3: 197 Cells"
## [1] "Cluster_lateral.Pallium.1: 219 Cells"
## [1] "Cluster_Dorsal.Pallium: 201 Cells"
## [1] "Cluster_lateral.Pallium.2: 113 Cells"
## [1] "Cluster_Sub.Pallium.1: 241 Cells"
Manuscript Fig. 2A

Manuscript Fig. 2A

Perform iterative graph-based clustering to find if discrete pallial sub-domain exist

Perform iterative clustering implemented in scrattch.hicat package

For more detail on the scrattch.hicat please refer to the package page.

Prepare the dataset for clustering with scrattch.hicat

Iterative clustering

Run the iterative clustering

The default iter_clust function use in this version of the scrattch.hicat package does not allow to set the k.param argument. We modify this function to allow this argument to be set to other values.

## [1] "test-iter_clust"
##   Finding nearest neighbors...DONE ~ 0.026 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.048 s
##   Build undirected graph from the weighted links...DONE ~ 0.057 s
##   Run louvain clustering on the graph ...DONE ~ 0.034 s
##   Return a community class
##   -Modularity value: 0.6822028 
##   -Number of clusters: 12[1] "test-iter_clust.1"
##   Finding nearest neighbors...DONE ~ 0.015 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.044 s
##   Build undirected graph from the weighted links...DONE ~ 0.046 s
##   Run louvain clustering on the graph ...DONE ~ 0.021 s
##   Return a community class
##   -Modularity value: 0.6939065 
##   -Number of clusters: 12[1] "test-iter_clust.2"
##   Finding nearest neighbors...DONE ~ 0 s
##   Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 0.008 s
##   Build undirected graph from the weighted links...DONE ~ 0.009 s
##   Run louvain clustering on the graph ...DONE ~ 0.002 s
##   Return a community class
##   -Modularity value: 0.7585217 
##   -Number of clusters: 7

Session Info

## [1] "09 novembre, 2020, 10,20"
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
##  [1] splines   stats4    parallel  stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] limma_3.42.0          Rphenograph_0.99.1    igraph_1.2.5         
##  [4] matrixStats_0.55.0    viridis_0.5.1         viridisLite_0.3.0    
##  [7] wesanderson_0.3.6     RColorBrewer_1.1-2    gridExtra_2.3        
## [10] reshape_0.8.8         ggExtra_0.9           scrattch.vis_0.0.210 
## [13] purrr_0.3.3           ggbeeswarm_0.6.0      dplyr_0.8.3          
## [16] scrattch.hicat_0.0.16 cluster_2.1.0         princurve_2.1.4      
## [19] monocle_2.14.0        DDRTree_0.1.5         irlba_2.3.3          
## [22] VGAM_1.1-2            Biobase_2.46.0        BiocGenerics_0.32.0  
## [25] Seurat_2.3.4          Matrix_1.2-17         cowplot_1.0.0        
## [28] ggplot2_3.2.1        
## 
## loaded via a namespace (and not attached):
##   [1] snow_0.4-3           backports_1.1.5      Hmisc_4.3-0         
##   [4] plyr_1.8.4           lazyeval_0.2.2       densityClust_0.3    
##   [7] fastICA_1.2-2        digest_0.6.25        foreach_1.4.7       
##  [10] htmltools_0.5.0      lars_1.2             gdata_2.18.0        
##  [13] magrittr_1.5         checkmate_1.9.4      gclus_1.3.2         
##  [16] mixtools_1.1.0       ROCR_1.0-7           R.utils_2.9.0       
##  [19] docopt_0.6.1         colorspace_1.4-1     ggrepel_0.8.1       
##  [22] xfun_0.18            sparsesvd_0.2        crayon_1.3.4        
##  [25] jsonlite_1.7.0       zeallot_0.1.0        survival_2.44-1.1   
##  [28] zoo_1.8-6            iterators_1.0.12     ape_5.3             
##  [31] glue_1.4.1           registry_0.5-1       gtable_0.3.0        
##  [34] kernlab_0.9-29       prabclus_2.3-1       DEoptimR_1.0-8      
##  [37] scales_1.1.0         pheatmap_1.0.12      bibtex_0.4.2        
##  [40] miniUI_0.1.1.1       Rcpp_1.0.5           metap_1.1           
##  [43] dtw_1.21-3           xtable_1.8-4         htmlTable_1.13.2    
##  [46] reticulate_1.13      foreign_0.8-72       bit_4.0.4           
##  [49] proxy_0.4-23         mclust_5.4.5         SDMTools_1.1-221.1  
##  [52] Formula_1.2-3        tsne_0.1-3           htmlwidgets_1.5.1   
##  [55] httr_1.4.1           FNN_1.1.3            gplots_3.0.1.1      
##  [58] fpc_2.2-3            acepack_1.4.1        modeltools_0.2-22   
##  [61] ica_1.0-2            farver_2.0.1         pkgconfig_2.0.3     
##  [64] R.methodsS3_1.7.1    flexmix_2.3-15       nnet_7.3-14         
##  [67] labeling_0.3         later_1.0.0          tidyselect_0.2.5    
##  [70] rlang_0.4.7          reshape2_1.4.3       munsell_0.5.0       
##  [73] tools_3.6.3          ggridges_0.5.1       fastmap_1.0.1       
##  [76] evaluate_0.14        stringr_1.4.0        yaml_2.2.1          
##  [79] npsurv_0.4-0         knitr_1.26           bit64_4.0.2         
##  [82] fitdistrplus_1.0-14  robustbase_0.93-5    caTools_1.17.1.2    
##  [85] RANN_2.6.1           dendextend_1.12.0    pbapply_1.4-2       
##  [88] nlme_3.1-141         mime_0.7             slam_0.1-46         
##  [91] R.oo_1.23.0          hdf5r_1.3.2.9000     compiler_3.6.3      
##  [94] rstudioapi_0.11      beeswarm_0.2.3       png_0.1-7           
##  [97] lsei_1.2-0           tibble_2.1.3         stringi_1.4.6       
## [100] highr_0.8            lattice_0.20-41      HSMMSingleCell_1.6.0
## [103] vctrs_0.2.0          pillar_1.4.2         lifecycle_0.1.0     
## [106] combinat_0.0-8       Rdpack_0.11-0        lmtest_0.9-37       
## [109] data.table_1.12.6    bitops_1.0-6         seriation_1.2-9     
## [112] gbRd_0.4-11          httpuv_1.5.2         R6_2.4.1            
## [115] latticeExtra_0.6-28  TSP_1.1-10           promises_1.1.0      
## [118] KernSmooth_2.23-15   vipor_0.4.5          codetools_0.2-16    
## [121] MASS_7.3-53          gtools_3.8.1         assertthat_0.2.1    
## [124] withr_2.1.2          qlcMatrix_0.9.7      mgcv_1.8-33         
## [127] diptest_0.75-7       doSNOW_1.0.18        grid_3.6.3          
## [130] rpart_4.1-15         tidyr_1.0.0          class_7.3-17        
## [133] rmarkdown_2.5        segmented_1.0-0      Rtsne_0.15          
## [136] shiny_1.4.0          base64enc_0.1-3

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France

LS0tCnRpdGxlOiAiSW52ZXN0aWdhdGlvbiBvZiB0aGUgYXBpY2FsIHByb2dlbml0b3JzIGRpdmVyc2l0eSIKYXV0aG9yOgogIC0gTWF0dGhpZXUgTW9yZWF1XltJbnN0aXR1dGUgb2YgUHN5Y2hpYXRyeSBhbmQgTmV1cm9zY2llbmNlIG9mIFBhcmlzLCBJTlNFUk0gVTEyNjYsIDc1MDE0LCBQYXJpcywgRnJhbmNlXSwgbWF0dGhpZXUubW9yZWF1QGluc2VybS5mcgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGRmX3ByaW50OiB0aWJibGUKICAgIGhpZ2hsaWdodDogaGFkZG9jawogICAgaW5jbHVkZXM6CiAgICAgIGluX2hlYWRlcjogaGVhZGVyLmh0bWwKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwotLS0KCmBgYHtjc3MsIGVjaG89RkFMU0V9CmgxIHsKICBmb250LXNpemU6IDM0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjZTY0ZDAwOwogIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQpoMS50aXRsZSB7CiAgZm9udC1zaXplOiA0MHB4OwogIG1hcmdpbi10b3A6IDJyZW07CiAgbWFyZ2luLWJvdHRvbTogMXJlbTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgyIHsKICBmb250LXNpemU6IDMwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9CmgzIHsKICBmb250LXNpemU6IDI0cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg0IHsKICBmb250LXNpemU6IDIwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cmg1IHsKICBmb250LXNpemU6IDE4cHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIGNvbG9yOiAjMDAwMDAwOwp9Cgouc2Nyb2xsLTEwMCB7CiAgbWF4LWhlaWdodDogMjAwcHg7CiAgb3ZlcmZsb3cteTogYXV0bzsKICBiYWNrZ3JvdW5kLWNvbG9yOiBpbmhlcml0Owp9CgpwIHsKICBmb250LXNpemU6IDE2cHg7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcuYWxpZ24gPSAnY2VudGVyJywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKYGBgCgojIExvYWQgbGlicmFyaWVzIGFuZCBRQ0ZpbHRlcmVkIGRhdGFzZXQKCmBgYHtyIH0KIyBMb2FkIGxpYnJhcnkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkobW9ub2NsZSkKbGlicmFyeShwcmluY3VydmUpCmxpYnJhcnkoY2x1c3RlcikKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeShzY3JhdHRjaC5oaWNhdCkKbGlicmFyeShzY3JhdHRjaC52aXMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ0V4dHJhKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlc2hhcGUpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeSh3ZXNhbmRlcnNvbikKbGlicmFyeSh2aXJpZGlzKQoKI1NldCBnZ3Bsb3QgdGhlbWUgYXMgY2xhc3NpYwp0aGVtZV9zZXQodGhlbWVfY2xhc3NpYygpKQpgYGAKCmBgYHtyfQojIExvYWQgdGhlIGZ1bGwgYW5ub3RhdGVkIGRhdGFzZXQKQWxsY2VsbHMuZGF0YSA8LSByZWFkUkRTKCIuL1FDLmZpbHRlcmVkLmNlbGxzLlJEUyIpCmBgYAoKIyBFeHRyYWN0IEFwaWNhbCBwcm9nZW5pdG9ycyBhbmQgY29tcHV0ZSBQc2V1ZG8tRG9yc29WZW50cmFsIHNjb3JlCgojIyBFeHRyYWN0IGFwaWNhbCBwcm9nZW5pdG9ycyBhbmQgZmlsdGVyIHRoZSBnZW5lIGV4cHJlc3Npb24gbWF0cml4CgpXZSBwZXJmb3JtIEttZWFucyBjbHVzdGVyaW5nIG9uIHRoZSAyIGNlbGwgc3RhdGUgc2NvcmVzIDoKCi0gQXBpY2FsIHByb2dlbml0b3JzIGBBUGAKLSBCYXNhbCBwcm9nZW5pdG9ycyBgQlBgCgpgYGB7ciB9CnNldC5zZWVkKDEwMCkKI0stbWVhbnMgY2x1c3RlcmluZyBiYXNlZCBvbiBBUCwgQlAgc2NvcmVzIGFjcm9zcyBjZWxscwpjbCA8LSBrbWVhbnMoY2JpbmQoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkQVBfc2lnbmF0dXJlMSwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkQlBfc2lnbmF0dXJlMSksIDMpCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJGttZWFuQ2x1c3QgPC0gcGFzdGUwKCJDbHVzdC4iLGNsJGNsdXN0ZXIpCmBgYAoKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpfQpjb2wucGFsIDwtIHdlc19wYWxldHRlKCJHcmFuZEJ1ZGFwZXN0MSIsIDMsIHR5cGUgPSAiZGlzY3JldGUiKQoKcDEgPC0gZ2dwbG90KEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBhZXMoeD1BUF9zaWduYXR1cmUxLCB5PUJQX3NpZ25hdHVyZTEsIGNvbG91ciA9IGttZWFuQ2x1c3QpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2wucGFsKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKZ2dNYXJnaW5hbChwMSwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiKSA7IHJtKHAxKQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gImttZWFuQ2x1c3QiLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICBjb2xzLnVzZSA9IGNvbC5wYWwsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IEYpCmBgYAoKV2UgdGhlbiBleHRyYWN0IHRoZSBnbHV0YW1hdGVyZ2ljIG5ldXJvbiBicmFuY2hlIGFzIGJlZWluZyB0aGUgS21lYW5zIGNsdXN0ZXIgd2l0aCB0aGUgaGlnaGVzdCBtZWFuIGBBcGljYWwgcHJvZ2VuaXRvcmAgc2lnbmF0dXJlCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KI0ZpbiBjbHVzdGVyIHdpaHQgdGhlIGhpZ2hlc3QgbWVhbiBBUHNjb3JlCk1lYW5LY2x1c3QuQVBzY29yZSA8LSBhZ2dyZWdhdGUoQVBfc2lnbmF0dXJlMSB+IGttZWFuQ2x1c3QsIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBtZWFuKQpBUGNsdXN0IDwtIE1lYW5LY2x1c3QuQVBzY29yZSAlPiUgZmlsdGVyKEFQX3NpZ25hdHVyZTEgPT0gbWF4KEFQX3NpZ25hdHVyZTEpKSAlPiUgcHVsbChrbWVhbkNsdXN0KQoKI0V4dHJhY3QgYXBpY2FsIHByb2dlbml0b3JzIApiYXJjb2RlcyA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUgZmlsdGVyKGttZWFuQ2x1c3QgPT0gQVBjbHVzdCkgJT4lIHB1bGwoQmFyY29kZXMpCkFQLmRhdGEgPC0gIFN1YnNldERhdGEoQWxsY2VsbHMuZGF0YSwgY2VsbHMudXNlID0gYmFyY29kZXMgLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKCiNGdXJ0aGVyIGZpbHRlciB0aGUgMyBvdXRsaWVyIGNlbGxzIGJhc2VkIG9uIHNwcmluZyBjb29yZGluYXRlcwpjZWxscyA8LSByb3duYW1lcyhBUC5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbQVAuZGF0YUBkciRzcHJpbmdAY2VsbC5lbWJlZGRpbmdzWywyXSA+IDI1MCxdKQpBUC5kYXRhIDwtICBTdWJzZXREYXRhKEFQLmRhdGEsIGNlbGxzLnVzZSA9IGNlbGxzICwgc3Vic2V0LnJhdyA9IFQsICBkby5jbGVhbiA9IEYpCgpEaW1QbG90KEFQLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAia21lYW5DbHVzdCIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGNvbHMudXNlID0gY29sLnBhbCwKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgojIyBGaWx0ZXIgZ2VuZSBjb3VudHMgbWF0cml4CgpgYGB7cn0KI1JlbW92ZSBub24gZXByZXNzZWQgZ2VuZXMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhBUC5kYXRhQGRhdGEgPiAwKQpnZW5lcy51c2UgPC0gbmFtZXMoeCA9IG51bS5jZWxsc1t3aGljaCh4ID0gbnVtLmNlbGxzID49IDIwKV0pCkFQLmRhdGFAcmF3LmRhdGEgPC0gQVAuZGF0YUByYXcuZGF0YVtnZW5lcy51c2UsIF0KQVAuZGF0YUBkYXRhIDwtIEFQLmRhdGFAZGF0YVtnZW5lcy51c2UsIF0KCiNOb3JtYWxpemUgYW5kIFNjYWxlIHRoZSBkYXRhCkFQLmRhdGEgPC0gTm9ybWFsaXplRGF0YShvYmplY3QgPSBBUC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZS5mYWN0b3IgPSByb3VuZChtZWRpYW4oQVAuZGF0YUBtZXRhLmRhdGEkblVNSSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCgpBUC5kYXRhIDwtIEZpbmRWYXJpYWJsZUdlbmVzKG9iamVjdCA9IEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuLmZ1bmN0aW9uID0gRXhwTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNpb24uZnVuY3Rpb24gPSBMb2dWTVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4Lmxvdy5jdXRvZmYgPSAwLjAxMjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4LmhpZ2guY3V0b2ZmID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkuY3V0b2ZmID0gMSwgZG8ucGxvdCA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5LnByb2dyZXNzID0gRikKCkFQLmRhdGEgPC0gU2NhbGVEYXRhKG9iamVjdCA9IEFQLmRhdGEsIHZhcnMudG8ucmVncmVzcyA9IGMoIkNDLkRpZmZlcmVuY2UiLCJwZXJjZW50Lm1pdG8iLCAiblVNSSIpLCBkaXNwbGF5LnByb2dyZXNzID0gRikKYGBgCgojIyBJbXBvcnQgU3ByaW5nIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbgoKKipDZWxsIGN5Y2xlIGFzc29jaWF0ZWQgZ2VuZXMqKiB3ZXJlIGV4Y2x1ZGVkIGZvciBQQ0EgZGltZW5zaW9uYWxpdHkgcmVkdWN0aW9uIGFuZCBTcHJpbmcgcGxvdCB3YXMgZ2VuZXJhdGluZyB3aXRoIHRoZXNlIHBhcmFtZXRlciA6CgpgYGAKTnVtYmVyIG9mIGNlbGxzOiAxNjQ4Ck51bWJlciBvZiBnZW5lcyB0aGF0IHBhc3NlZCBmaWx0ZXI6IDg1NwpNaW4gZXhwcmVzc2luZyBjZWxscyAoZ2VuZSBmaWx0ZXJpbmcpOiAzCk1pbiBudW1iZXIgb2YgVU1JcyAoZ2VuZSBmaWx0ZXJpbmcpOiAzCkdlbmUgdmFyaWFiaWxpdHkgJWlsZSAoZ2VuZSBmaWx0ZXJpbmcpOiA5MApOdW1iZXIgb2YgcHJpbmNpcGFsIGNvbXBvbmVudHM6IDcKTnVtYmVyIG9mIG5lYXJlc3QgbmVpZ2hib3JzOiAyMApOdW1iZXIgb2YgZm9yY2UgbGF5b3V0IGl0ZXJhdGlvbnM6IDUwMApgYGAKCmBgYHtyfQojSW1wb3J0IFNwcmluZyBjb29yZGluYXRlcyBjYWxjdWxhdGVkIHdpdGhvdXQgY2VsbCBjeWNsZSBnZW5lcwpDb29yZGluYXRlcyA8LSByZWFkLnRhYmxlKCIuL1Byb2dlbml0b3JzL0UxMi5BUC5Db29yZGluYXRlcy50eHQiLCBzZXA9IiwiLCBoZWFkZXIgPSBGKVssYygyLDMpXQpyb3duYW1lcyhDb29yZGluYXRlcykgPC0gcm93bmFtZXMoQVAuZGF0YUBtZXRhLmRhdGEpCkFQLmRhdGEgPC0gU2V0RGltUmVkdWN0aW9uKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbi50eXBlID0gInNwcmluZy5BUCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNsb3QgPSAiY2VsbC5lbWJlZGRpbmdzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3LmRhdGEgPSBhcy5tYXRyaXgoQ29vcmRpbmF0ZXMpKQpBUC5kYXRhQGRyJHNwcmluZy5BUEBrZXkgPC0gInNwcmluZy5BUCIKY29sbmFtZXMoQVAuZGF0YUBkciRzcHJpbmcuQVBAY2VsbC5lbWJlZGRpbmdzKSA8LSBwYXN0ZTAoR2V0RGltUmVkdWN0aW9uKG9iamVjdCA9IEFQLmRhdGEsIHJlZHVjdGlvbi50eXBlID0gInNwcmluZy5BUCIsc2xvdCA9ICJrZXkiKSwgYygxLDIpKQoKYGBgCgojIyBGaXQgYSBwcmluY2lwYWwgY3VydmUgb3ZlciB0aGUgQVAgaW4gdGhlIFNwcmluZyBzcGFjZQoKYGBge3J9CmRhdGEgPC0gZGF0YS5mcmFtZShzcHJpbmdBUC4xID0gQVAuZGF0YUBkciRzcHJpbmcuQVBAY2VsbC5lbWJlZGRpbmdzWywxXSwKICAgICAgICAgICAgICAgICAgIHNwcmluZ0FQLjIgPSBBUC5kYXRhQGRyJHNwcmluZy5BUEBjZWxsLmVtYmVkZGluZ3NbLDJdLAogICAgICAgICAgICAgICAgICAgc3ByaW5nMSA9IEFQLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1ssMV0sCiAgICAgICAgICAgICAgICAgICBzcHJpbmcyID0gQVAuZGF0YUBkciRzcHJpbmdAY2VsbC5lbWJlZGRpbmdzWywyXSkKCiMgRml0IHRoZSBwcmluY2lwYWwgY3VydmUKZml0IDwtIHByaW5jaXBhbF9jdXJ2ZShhcy5tYXRyaXgoZGF0YVssMToyXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J2xvd2VzcycsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICBmID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmV0Y2g9MCwKICAgICAgICAgICAgICAgICAgICAgICBwbG90X2l0ZXJhdGlvbnMgPSBGKQpgYGAKCmBgYHtyfQpEb3Jzb1ZlbnRyYWwuU2NvcmUgPC0gZml0JGxhbWJkYS9tYXgoZml0JGxhbWJkYSkgI1RoZSBhY3R1YWwgc3BldWRvdGltZQpwYy5saW5lIDwtIGFzLmRhdGEuZnJhbWUoZml0JHNbb3JkZXIoZml0JGxhbWJkYSksXSkgI1RoZSBwcmluY2lwYWwgY3VydmUgc21vb3RoZWQKCmRhdGEkUGhhc2UgPC0gYXMuY2hhcmFjdGVyKEFQLmRhdGFAbWV0YS5kYXRhJFBoYXNlKQpkYXRhJERvcnNvVmVudHJhbC5TY29yZSA8LSBEb3Jzb1ZlbnRyYWwuU2NvcmUKCiMgRGlyZWN0aW9uIG9mIHRoZSBtYXR1cmF0aW9uIHNjb3JlIHVzaW5nIFpidGIyMCBleHByZXNzaW9uIChyZXZlcnRlIGlmIHBvc2l0aXZlIGNvcnJlbGF0aW9uKQppZiAoY29yKGRhdGEkRG9yc29WZW50cmFsLlNjb3JlLCBBUC5kYXRhQGRhdGFbJ1pidGIyMCcsIF0pID4gMCkgeyBkYXRhJERvcnNvVmVudHJhbC5TY29yZSA8LSAtKGRhdGEkRG9yc29WZW50cmFsLlNjb3JlIC0gbWF4KGRhdGEkRG9yc29WZW50cmFsLlNjb3JlKSl9CgpBUC5kYXRhQG1ldGEuZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUgPC0gZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KI1Bsb3QgQ2VsbCBvbnRvIFBDMSBhbmQgUEMyIHdpdGggcHJpbmNpcGFsIGN1cnZlCmdncGxvdChkYXRhLCBhZXMoc3ByaW5nQVAuMSwgc3ByaW5nQVAuMikpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9UGhhc2UpLCBzaXplPTIsIHNoYXBlPTE2LCB2YWx1ZXM9Y29sLnBhbCkgKwogIGdlb21fbGluZShkYXRhPXBjLmxpbmUsIGNvbG9yPSdyZWQnLCBzaXplPTAuNzcpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gNUEifQojUGxvdCBTcGV1ZG90aW1lIGNvbG9yIGdyYWRpZW50IG9uIHRoZSBjZWxsIGN5Y2xlIGZpbHRlcmVkIFNwcmluZyBlbWJiZWRpbmcKZ2dwbG90KGRhdGEsIGFlcyhzcHJpbmdBUC4xLCBzcHJpbmdBUC4yKSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPURvcnNvVmVudHJhbC5TY29yZSksIHNpemU9Miwgc2hhcGU9MTYpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzKGRpcmVjdGlvbiA9IC0xKSArCiAgZ2VvbV9saW5lKGRhdGE9cGMubGluZSwgY29sb3I9J3JlZCcsIHNpemU9MC43NykKYGBgCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KX0KI1Bsb3QgU3BldWRvdGltZSBjb2xvciBncmFkaWVudCBvbiB0aGUgU3ByaW5nIGVtYmJlZGluZyBjYWxjdWxhdGVkIGZyb20gZnVsbCBkYXRhc2V0CmdncGxvdChkYXRhLCBhZXMoc3ByaW5nMSwgc3ByaW5nMikpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9RG9yc29WZW50cmFsLlNjb3JlKSwgc2l6ZT0yLCBzaGFwZT0xNikgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEpIApgYGAKCiMgRmluZCBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWxvbmcgdGhlIHBzZXVkbyBEViBheGlzCgojIyBJbml0aWFsaXplIGEgbW9ub2NsZSBvYmplY3QKCmBgYHtyfQojIFRyYW5zZmVydCBtZXRhZGF0YSAKbWV0YS5kYXRhIDwtIGRhdGEuZnJhbWUoYmFyY29kZSA9IHJvd25hbWVzKEFQLmRhdGFAbWV0YS5kYXRhKSwKICAgICAgICAgICAgICAgICAgICAgICAgQ2x1c3RlciA9IEFQLmRhdGFAbWV0YS5kYXRhJG9sZC5pZGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgRG9yc29WZW50cmFsLlNjb3JlID0gIEFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZSwKICAgICAgICAgICAgICAgICAgICAgICAgQ2VsbGN5Y2xlUGhhc2UgPSBBUC5kYXRhQG1ldGEuZGF0YSRQaGFzZSwKICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID0gcm93bmFtZXMoQVAuZGF0YUBtZXRhLmRhdGEpKQogICAgICAgICAgICAgICAgICAgCkFubm90LmRhdGEgIDwtIG5ldygnQW5ub3RhdGVkRGF0YUZyYW1lJywgZGF0YSA9IG1ldGEuZGF0YSkKCiMgVHJhbnNmZXJ0IGNvdW50IGRhdGEKY291bnQuZGF0YSA9IGRhdGEuZnJhbWUoZ2VuZV9zaG9ydF9uYW1lID0gcm93bmFtZXMoQVAuZGF0YUByYXcuZGF0YSksCiAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IHJvd25hbWVzKEFQLmRhdGFAcmF3LmRhdGEpKQoKZmVhdHVyZS5kYXRhIDwtIG5ldygnQW5ub3RhdGVkRGF0YUZyYW1lJywgZGF0YSA9IGNvdW50LmRhdGEpCgojIENyZWF0ZSB0aGUgQ2VsbERhdGFTZXQgb2JqZWN0CmdibV9jZHMgPC0gbmV3Q2VsbERhdGFTZXQoYXMubWF0cml4KEFQLmRhdGFAcmF3LmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBoZW5vRGF0YSA9IEFubm90LmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHVyZURhdGEgPSBmZWF0dXJlLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbG93ZXJEZXRlY3Rpb25MaW1pdCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbkZhbWlseSA9IG5lZ2Jpbm9taWFsKCkpCmBgYAoKCmBgYHtyfQpnYm1fY2RzIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZ2JtX2NkcykKZ2JtX2NkcyA8LSBlc3RpbWF0ZURpc3BlcnNpb25zKGdibV9jZHMpCmdibV9jZHMgPC0gZGV0ZWN0R2VuZXMoZ2JtX2NkcywgbWluX2V4cHIgPSAwLjEpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQVAuZGF0YSIsICJnYm1fY2RzIildKQpgYGAKCiMjIFRlc3QgZWFjaCBnZW5lIHRyZW5kIG92ZXIgcHNldWRvLURWIHNjb3JlCgpgYGB7cn0KIyBFeGNsdWRlIGNlbGwgY3ljbGUgYXNzb2NpYXRlZCBnZW5lcwpDQ2dlbmVzIDwtIGFzLmNoYXJhY3RlcihyZWFkLnRhYmxlKCIuL1Byb2dlbml0b3JzL0NlbGxDeWNsZUdlbmVzLmNzdiIsIHNlcCA9ICJcdCIsIGhlYWRlciA9IEYpWywxXSkKSW5wdXQuZ2VuZXMgPC0gQVAuZGF0YUB2YXIuZ2VuZXNbIUFQLmRhdGFAdmFyLmdlbmVzICVpbiUgQ0NnZW5lc10KYGBgCgoKYGBge3J9CiMgUGVyZm9ybSB0aGUgdGVzdCBmb3IgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYXMgYSBmdW5jdGlvbiBvZiBwc2V1ZG8tRFYgc2NvcmUgd2hpbGUgY29udHJvbGluZyBmb3IgY2VsbCBjeWNsZSBwaGFzZQpEVi5BeGlzLmdlbmVzIDwtIGRpZmZlcmVudGlhbEdlbmVUZXN0KGdibV9jZHNbSW5wdXQuZ2VuZXMsXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbE1vZGVsRm9ybXVsYVN0ciA9ICJ+c20ubnMoRG9yc29WZW50cmFsLlNjb3JlLCBkZiA9IDMpKkNlbGxjeWNsZVBoYXNlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVkdWNlZE1vZGVsRm9ybXVsYVN0ciA9ICJ+Q2VsbGN5Y2xlUGhhc2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IGRldGVjdENvcmVzKCkgLTIpCgojIEZpbHRlciBnZW5lcyB3aXRoIGEgRkRSIDwgMC4wMDEKRFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQgPC0gRFYuQXhpcy5nZW5lcyAlPiUgZmlsdGVyKHF2YWwgPCAxZS0zKQpgYGAKCgojIyBTbW9vdGggc2lnbmlmaWNhdGl2ZSBnZW5lIGV4cHJlc3Npb24gcHNldWRvLURWIGF4aXMKCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBwc2V1ZG8tRFYgdmVjdG9yIG9mIDUwMCBwb2ludHMKblBvaW50cyA8LSA1MDAKbmV3X2RhdGEgPC0gZGF0YS5mcmFtZShEb3Jzb1ZlbnRyYWwuU2NvcmUgPSBzZXEobWluKHBEYXRhKGdibV9jZHMpJERvcnNvVmVudHJhbC5TY29yZSksIG1heChwRGF0YShnYm1fY2RzKSREb3Jzb1ZlbnRyYWwuU2NvcmUpLCBsZW5ndGgub3V0ID0gblBvaW50cykpCgojIFNtb290aCBnZW5lIGV4cHJlc3Npb24KU21vb3RoLmN1cnZlLm1hdHJpeCA8LSBnZW5TbW9vdGhDdXJ2ZXMoZ2JtX2Nkc1thcy5jaGFyYWN0ZXIoRFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQkZ2VuZV9zaG9ydF9uYW1lKSxdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmVuZF9mb3JtdWxhID0gIn5zbS5ucyhEb3Jzb1ZlbnRyYWwuU2NvcmUsIGRmID0gMykiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxhdGl2ZV9leHByID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3X2RhdGEgPSBuZXdfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29yZXM9IGRldGVjdENvcmVzKCkgLSAyKQpgYGAKCiMgQ2x1c3RlciBjZWxsIGJ5IHNpbWlsYXIgZXhwcmVzc2lvbiBwcm9maWxlcyBvbiB0aGUgcHNldWRvLURWIGF4aXMKCmBgYHtyfQpzZXQuc2VlZCgxMDApCiMgQ2x1c3RlciBjZWxscyB1c2luZyB0aGUgUGFydGl0aW9uaW5nIEFyb3VuZCBNZWRvaWRzIGFsZ29yaXRobQpDZWxscy5DbHVzdCA8LSBwYW0oYXMuZGlzdCgoMSAtIGNvcihTbW9vdGguY3VydmUubWF0cml4ICxtZXRob2QgPSAic3BlYXJtYW4iKSkpLCBrPTcpCkRvbWFpbmVzLkNsdXN0IDwtIGRhdGEuZnJhbWUoRG9tYWluZXMgPSBwYXN0ZTAoIkNsdXN0LiIsQ2VsbHMuQ2x1c3QkY2x1c3RlcmluZykpCmBgYAoKIyBDbHVzdGVyIGdlbmUgYnkgc2ltaWxhciBwcm9maWxlcyBvdmVyIHBzZXVkby1EViBheGlzCgojIyBQZXJmb3JtIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nCgpgYGB7cn0KIyBCdWlsZCBnZW5lcyBkZW5kcm9ncmFtCmRzdCA8LSBkaXN0KHQoc2NhbGUodChTbW9vdGguY3VydmUubWF0cml4KSkpLCBtZXRob2QgPSAibWFuaGF0dGFuIikKaGMgPC0gaGNsdXN0KGRzdCwgbWV0aG9kID0gIndhcmQuRCIpICMid2FyZC5EIgoKIyBTZXJpYXRlIHRoZSBkZW5kcm9ncmFtCmRlbmQgPC0gYXMuZGVuZHJvZ3JhbShoYykKZGVuZCA8LSBkZW5kZXh0ZW5kOjpzZXJpYXRlX2RlbmRyb2dyYW0oZGVuZCwgZHN0LCBtZXRob2Q9IkdXIikKCiMgRmluZCAxNSBjbHVzdGVyIGJhc2VkIG9uIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nCmNsdXN0ZXJzIDwtIGN1dHJlZShoYywgaz0xMCkKCkdlbmUuZHluYW1pcXVlIDwtIGRhdGEuZnJhbWUoR2VuZT0gbmFtZXMoY2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWw9IERWLkF4aXMuZ2VuZXMuRkRSLmZpbHRlcmVkJHB2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXZhbD1EVi5BeGlzLmdlbmVzLkZEUi5maWx0ZXJlZCRxdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bV9jZWxsc19leHByZXNzZWQ9RFYuQXhpcy5nZW5lcy5GRFIuZmlsdGVyZWQkbnVtX2NlbGxzX2V4cHJlc3NlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXYXZlcyA9IGFzLm51bWVyaWMoY2x1c3RlcnMpKSAlPiUgYXJyYW5nZShXYXZlcykKCnJvdy5uYW1lcyhHZW5lLmR5bmFtaXF1ZSkgPC0gR2VuZS5keW5hbWlxdWUkR2VuZQpHZW5lLmR5bmFtaXF1ZSRHZW5lLkNsdXN0ZXJzIDwtIHBhc3RlMCgiQ2x1c3QuIixHZW5lLmR5bmFtaXF1ZSRXYXZlcykKCndyaXRlLnRhYmxlKEdlbmUuZHluYW1pcXVlLCAiLi9Qcm9nZW5pdG9ycy9HZW5lLmR5bmFtaXF1ZS5jc3YiLCBzZXAgPSAiOyIsIHF1b3RlID0gRikKYGBgCgoKIyMgUGxvdCBnZW5lL2NlbGwgaGVhdG1hcAoKYGBge3IgZmlnLmRpbT1jKDcsIDkuMyksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gNUMifQphbm5vLmNvbG9ycyA8LSBsaXN0KERvbWFpbmVzID0gYyhDbHVzdC4xPSIjODNjM2I4IiwgQ2x1c3QuMj0iIzAwOWZkYSIsIENsdXN0LjM9IiMzZTY5YWMiLCBDbHVzdC40PSIjZTQ2YjZiIiwgQ2x1c3QuNT0iI2UzYzE0OCIsIENsdXN0LjY9IiNiN2QxNzQiLCBDbHVzdC43PSIjNjhiMDQxIiksCiAgICAgICAgICAgICAgICAgICAgR2VuZS5DbHVzdGVycyA9IGMoQ2x1c3QuMSA9IiNlYzc1NmQiICwgQ2x1c3QuMj0iI2ViY2IyZSIsIENsdXN0LjM9IiNiNzlmMGIiLCBDbHVzdC40PSIjNzI5M2M4IiwgQ2x1c3QuNT0iIzNjYTczZiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2x1c3QuNj0iIzllYzIyZiIsIENsdXN0Ljc9IiNjYzNhMWIiLCBDbHVzdC44PSIjNGNhYmRjIiwgQ2x1c3QuOT0iI2NjODc3OCIsIENsdXN0LjEwPSIjNDc4NGEyIikpCgpwaGVhdG1hcDo6cGhlYXRtYXAoU21vb3RoLmN1cnZlLm1hdHJpeCwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz0gYXMuaGNsdXN0KGRlbmQpLAogICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29scyA9IEYsCiAgICAgICAgICAgICAgICAgICBnYXBzX2NvbCA9IGN1bXN1bShhcy5udW1lcmljKHRhYmxlKERvbWFpbmVzLkNsdXN0JERvbWFpbmVzKSkpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSBHZW5lLmR5bmFtaXF1ZSAlPiUgZHBseXI6OnNlbGVjdChHZW5lLkNsdXN0ZXJzKSwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sID0gRG9tYWluZXMuQ2x1c3QsCiAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uX2NvbG9ycyA9IGFubm8uY29sb3JzLAogICAgICAgICAgICAgICAgICAgc2hvd19jb2xuYW1lcyA9IEYsCiAgICAgICAgICAgICAgICAgICBzaG93X3Jvd25hbWVzID0gVCwKICAgICAgICAgICAgICAgICAgIGZvbnRzaXplX3JvdyA9IDIsCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IHJldihicmV3ZXIucGFsKDExLCJSZEJ1IikpLAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKC0yLjUsMi41LCBsZW5ndGgub3V0ID0gMTEpLAogICAgICAgICAgICAgICAgICAgbWFpbiA9ICJHZW5lcyBleHByZXNzaW9uIGFsb25nIERvcnNvLVZlbnRyYWwgYXhpcyIpCmBgYAojI1Bsb3QgZ2VuZSBjbHVzdGVycyB0cmVuZHMKYGBge3IgZmlnLmRpbT1jKDYsIDkpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDVDIn0Kc291cmNlKCIuL2Z1bmN0aW9ucy9HZW5lc1RyZW5kUGxvdHMuUiIpCkNsdXN0ZXJzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgIFdoaWNoLmNsdXN0ZXIgPSAxOjEwLAogICAgICAgICAgICAgICBjbHVzdC5saXN0ID0gY2x1c3RlcnMsCiAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gImdsb2JhbCIsCiAgICAgICAgICAgICAgIHNwYW4gPSAxLAogICAgICAgICAgICAgICBTbW9vdGgubWV0aG9kID0gImF1dG8iLAogICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IFQpCmBgYAoKIyMgQXNzaWduIGRvbWFpbiBpZGVudGl0eQoKCldlIGFzc2lnbiBkb21haW4gaWRlbnRpdHkgYmFzZWQgb24gY2x1c3RlcnMnIHRyYW5zY3JpcHRpb25hbCBwcm9maWxlIGJ5IHNldHRpbmcgYm91bmRhcmllcyBvdmVyIHBzZXVkby1kdiBzY29yZQpgYGB7cn0KIyBTZXQgdGhlIGJvdW5kYXJ5IG92ZXIgc3BldWRvdGltZSBzY29yZQpuZXdfZGF0YSRjbHVzdGVyIDwtIERvbWFpbmVzLkNsdXN0JERvbWFpbmVzCkluZmVyZWQuRG9tYWluLmJvdW5kYXJ5IDwtIGFnZ3JlZ2F0ZShEb3Jzb1ZlbnRyYWwuU2NvcmUgfiBjbHVzdGVyLCBuZXdfZGF0YSwgbWF4KSAlPiUgcHVsbChEb3Jzb1ZlbnRyYWwuU2NvcmUpCgojIEFzc2lnbiBpZGVudGl0eSBiYXNlZCBvbiB0aGUgcG9zaXRpb24gb2YgdGhlIGNlbGwgb24gdGhlIHBzZXVkby1kdiBheGlzCkRvbWFpbmUuSWRlbnQgPC0gc2FwcGx5KEFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZSwKICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCl7IGlmKHg8SW5mZXJlZC5Eb21haW4uYm91bmRhcnlbMV0peyB4ID0gIlN1Yi5QYWxsaXVtLjEiCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZih4PiBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVsxXSAmIHg8IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzJdKXsgeCA9IlN1Yi5QYWxsaXVtLjIiCiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZih4PiBJbmZlcmVkLkRvbWFpbi5ib3VuZGFyeVsyXSAmIHg8IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzNdKXsgeCA9ICJTdWIuUGFsbGl1bS4zIiAKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHg+IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzNdICYgeDwgSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbNF0peyB4ID0gIlZlbnRyYWwuUGFsbGl1bSIKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKHg+IEluZmVyZWQuRG9tYWluLmJvdW5kYXJ5WzRdICYgeDwgSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbNV0peyB4ID0gImxhdGVyYWwuUGFsbGl1bS4xIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYoeD4gSW5mZXJlZC5Eb21haW4uYm91bmRhcnlbNl0peyB4ID0gIkRvcnNhbC5QYWxsaXVtIgogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgeD0ibGF0ZXJhbC5QYWxsaXVtLjIifSkKCiMgVHJhbnNmZXJ0IHRoZSBpZGVudGl0eSB0byB0aGUgU2V1cmF0IG9iamVjdApBUC5kYXRhQG1ldGEuZGF0YSREb21haW5lIDwtIERvbWFpbmUuSWRlbnQKQVAuZGF0YSA8LSBTZXRBbGxJZGVudChBUC5kYXRhLCBpZCA9ICJEb21haW5lIikKYGBgCgoKYGBge3IgZmlnLmRpbT1jKDEwLDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIDVEIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiR3N4MiIsICJEYngxIiwgIkdtMjkyNjAiLCAiVGZhcDJjIiwgIkVteDEiLCAiTHJybjEiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CkRpbVBsb3QoQVAuZGF0YSwKICAgICAgICAgZ3JvdXAuYnkgPSAiRG9tYWluZSIsCiAgICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICAgZGltLjEgPSAxLAogICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgIGRvLmxhYmVsPUYsCiAgICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgICBuby5sZWdlbmQgPSBGLAogICAgICAgICBjb2xzLnVzZSA9IHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiIzgzQzNCOCIsICIjMDA5RkRBIiwgIiMzRTY5QUMiLCAiI0U0NkI2QiIpKQogICAgICAgICApCmBgYAoKIyBQbG90IEZpZ3VyZSA1QgoKYGBge3J9CiNsb2FkIGZ1bGwgZGF0YXNldApBbGxjZWxscy5kYXRhIDwtIHJlYWRSRFMoIi4vUUMuZmlsdGVyZWQuY2VsbHMuUkRTIikKCiNUcmFuc2ZlciB0aGUgaWRlbnRpdGllcwpSZW5hbWUuQ2x1c3QgPC0gIGZ1bmN0aW9uKENsdXN0ZGF0YSwgUmF3UUNkYXRhKSB7CiAgdW5DbHVzdGVyZWQuY2VsbHMgPC0gUmF3UUNkYXRhQG1ldGEuZGF0YSRCYXJjb2RlcwogIFJhd1FDZGF0YSA8LSBTZXRJZGVudChSYXdRQ2RhdGEsIGNlbGxzLnVzZSA9IHVuQ2x1c3RlcmVkLmNlbGxzLCBpZGVudC51c2UgPSAiQWxsLlVuY2x1c3RlcmVkLkNlbGxzIikKICAKICBmb3IoaSBpbiB1bmlxdWUoQ2x1c3RkYXRhQG1ldGEuZGF0YSREb21haW5lKSl7CiAgTmV3LmlkZW50IDwtIGkKICBCYXJjb2RlcyA8LSByb3duYW1lcyhzdWJzZXQoQ2x1c3RkYXRhQG1ldGEuZGF0YSwgQ2x1c3RkYXRhQG1ldGEuZGF0YSREb21haW5lID09IGkpKQogIHByaW50KHBhc3RlMCgiQ2x1c3Rlcl8iLGksIjogIixsZW5ndGgoQmFyY29kZXMpLCAiIENlbGxzIikpCiAgQmFyY29kZXMgPC0gQmFyY29kZXNbQmFyY29kZXMgJWluJSByb3duYW1lcyhSYXdRQ2RhdGFAbWV0YS5kYXRhKV0KICBSYXdRQ2RhdGEgPC0gU2V0SWRlbnQoUmF3UUNkYXRhLCBjZWxscy51c2UgPSBCYXJjb2RlcyAsaWRlbnQudXNlID0gcGFzdGUwKCJBUC4iLGkpKQogIH0KICByZXR1cm4oUmF3UUNkYXRhKQp9CgpBbGxjZWxscy5kYXRhIDwtIFJlbmFtZS5DbHVzdChDbHVzdGRhdGEgPSBBUC5kYXRhLCBSYXdRQ2RhdGEgPSBBbGxjZWxscy5kYXRhKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg1LjMsIDQpLCAsIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gNUIifQpjb2xvcnMgPC0gIGMoIiM5Njk2OTYiLHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiIzgzQzNCOCIsICIjMDA5RkRBIiwgIiMzRTY5QUMiLCAiI0U0NkI2QiIpKSkKCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMiwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzKQpgYGAKCmBgYHtyfQpybShsaXN0ID0gbHMoKVshbHMoKSAlaW4lIGMoIkFQLmRhdGEiKV0pCmBgYAoKIyBQbG90IHRoZSByZXByZXNlbnRhdGl2ZSBnZW5lIG9mIHRoZSBGaWd1cmUgUzYKCmBgYHtyfQojIExvYWQgY3VzdG9tIHBsb3R0aW5nIGZ1bmN0aW9ucwpzb3VyY2UoIi4vZnVuY3Rpb25zL0dlbmVzVHJlbmRQbG90cy5SIikKYGBgCgojIyBDbHVzdGVyIDYKCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2QSJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIkRseDEiLCAiQW5vMSIsICJEbHgyIiwgIk9saWcyIiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMjIENsdXN0ZXIgMgoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZCIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiT3R4MiIsICJaYnRiMjAiLCAiU2l4MyIsICJBc2NsMSIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIyBDbHVzdGVyIDMKCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2QyJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk1laXMxIiwgIlJvcmIiLCAiRXBoYTMiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyMgQ2x1c3RlciAxCgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkQifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJTZnJwMiIsICJFdmExYyIsICJTZW1hNWEiLCAiRmF0NCIpLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIyBDbHVzdGVyIDkKCmBgYHtyIGZpZy5kaW09YygxMCw2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLlM2RSJ9ClBsb3QuR2VuZXMudHJlbmQoQVAuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIkRtcnRhMiIsIkx5cGQ2IiwgIlBheDYiLCAiRG1ydGExIiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMjIENsdXN0ZXIgNSA/CgpgYGB7ciBmaWcuZGltPWMoMTAsNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy5TNkYifQpQbG90LkdlbmVzLnRyZW5kKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJFbXgxIiwgIkFyeCIsICJMbW8zIiksCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCiMjIENsdXN0ZXIgOQoKYGBge3IgZmlnLmRpbT1jKDEwLDYpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuUzZHIn0KUGxvdC5HZW5lcy50cmVuZChBUC5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiRmV6ZjIiLCAiRW14MiIsICJTcDgiKSwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKIyBUcmFuc2ZlcnQgdGhlc2UgaWRlbnQgb24gdGhlIGZ1bGwgZGF0YXNldCAoTWFudXNjcmlwdCBGaWcuIDJBKQoKYGBge3J9CiNsb2FkIGZ1bGwgZGF0YXNldApBbGxjZWxscy5kYXRhIDwtIHJlYWRSRFMoIi4vQ2x1c3RlcmVkLmNlbGxzLlJEUyIpCgojVHJhbnNmZXIgdGhlIGlkZW50aXRpZXMKUmVuYW1lLkNsdXN0IDwtICBmdW5jdGlvbihDbHVzdGRhdGEsIFJhd1FDZGF0YSkgewogIGZvcihpIGluIHVuaXF1ZShDbHVzdGRhdGFAbWV0YS5kYXRhJERvbWFpbmUpKXsKICAgIE5ldy5pZGVudCA8LSBpCiAgICBCYXJjb2RlcyA8LSByb3duYW1lcyhzdWJzZXQoQ2x1c3RkYXRhQG1ldGEuZGF0YSwgQ2x1c3RkYXRhQG1ldGEuZGF0YSREb21haW5lID09IGkpKQogICAgcHJpbnQocGFzdGUwKCJDbHVzdGVyXyIsaSwiOiAiLGxlbmd0aChCYXJjb2RlcyksICIgQ2VsbHMiKSkKICAgIEJhcmNvZGVzIDwtIEJhcmNvZGVzW0JhcmNvZGVzICVpbiUgcm93bmFtZXMoUmF3UUNkYXRhQG1ldGEuZGF0YSldCiAgICBSYXdRQ2RhdGEgPC0gU2V0SWRlbnQoUmF3UUNkYXRhLCBjZWxscy51c2UgPSBCYXJjb2RlcyAsaWRlbnQudXNlID0gcGFzdGUwKCJBUC4iLGkpKQogIH0KICByZXR1cm4oUmF3UUNkYXRhKQp9CgpBbGxjZWxscy5kYXRhIDwtIFJlbmFtZS5DbHVzdChDbHVzdGRhdGEgPSBBUC5kYXRhLCBSYXdRQ2RhdGEgPSBBbGxjZWxscy5kYXRhKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg4LCA2KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiAyQSJ9CmNvbG9yczIgPC0gIGMoIiM5Njk2OTYiLAogICAgICAgICAgICAgIHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiIzgzQzNCOCIsICIjMDA5RkRBIiwgIiMzRTY5QUMiLCAiI0U0NkI2QiIpKSwKICAgICAgICAgICAgICAiI2VjNzU2ZCIsICIjYzc3M2E3IiwgIiM3MjkzYzgiLCAiI2I3OWYwYiIsICIjM2NhNzNmIiwiIzMxYjZiZCIsCiAgICAgICAgICAgICAgIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsIiNlNmJiOWIiLCAiIzA0NmM5YSIsICIjNDc4NGEyIiAsICIjNDk5MGM5IikKCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMiwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzMikKYGBgCgpgYGB7cn0KQWxsY2VsbHMuZGF0YSA8LSBTdGFzaElkZW50KEFsbGNlbGxzLmRhdGEsIHNhdmUubmFtZSA9ICJDbHVzdGVyLmlkZW50IikKc2F2ZVJEUyhBbGxjZWxscy5kYXRhLCAiLi9DbHVzdGVyZWQuY2VsbHMuUkRTIikKc2F2ZVJEUyhBUC5kYXRhLCAiLi9BUC5kYXRhLlJEUyIpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQVAuZGF0YSIpXSkKYGBgCgoKIyBQZXJmb3JtIGl0ZXJhdGl2ZSBncmFwaC1iYXNlZCBjbHVzdGVyaW5nIHRvIGZpbmQgaWYgZGlzY3JldGUgcGFsbGlhbCBzdWItZG9tYWluIGV4aXN0CgojIyBFeHRyYWN0IHBhbGxpYWwgcHJvZ2VuaXRvcnMKCmBgYHtyfQojIEZpbHRlciBzdWJwYWxsaWFsIHByb2dlbml0b3JzCkFQLmlkZW50IDwtIHVuaXF1ZShBUC5kYXRhQGlkZW50KQpBUC5kYXRhIDwtICBTdWJzZXREYXRhKEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQudXNlID0gZ3JlcCgiU3ViIiwgQVAuaWRlbnQsIHZhbHVlID0gVCwgaW52ZXJ0ID0gVCksCiAgICAgICAgICAgICAgICAgICAgICAgc3Vic2V0LnJhdyA9IFQsCiAgICAgICAgICAgICAgICAgICAgICAgZG8uY2xlYW4gPSBGKQoKIyBSZXNldCB0aGUgcHNldWRvLURWIHNjb3JlIHRvIFswLDFdCnNjb3JlIDwtIEFQLmRhdGFAbWV0YS5kYXRhJERvcnNvVmVudHJhbC5TY29yZQpBUC5kYXRhQG1ldGEuZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUgPC0gKHNjb3JlIC0gbWluKHNjb3JlKSkgLyAobWF4KHNjb3JlKSAtIG1pbihzY29yZSkpCmBgYAoKIyMgUGVyZm9ybSBpdGVyYXRpdmUgY2x1c3RlcmluZyBpbXBsZW1lbnRlZCBpbiBzY3JhdHRjaC5oaWNhdCBwYWNrYWdlCgpGb3IgbW9yZSBkZXRhaWwgb24gdGhlIHNjcmF0dGNoLmhpY2F0IHBsZWFzZSByZWZlciB0byB0aGUgW3BhY2thZ2UgcGFnZV0oaHR0cHM6Ly9naXRodWIuY29tL0FsbGVuSW5zdGl0dXRlL3NjcmF0dGNoLmhpY2F0KS4gCgojIyMgUHJlcGFyZSB0aGUgZGF0YXNldCBmb3IgY2x1c3RlcmluZyB3aXRoIHNjcmF0dGNoLmhpY2F0CgojIyMjIEluZGVwZW5kZW50IGdlbmUgZmlsdGVyaW5nCgpXZSBkZWNpZGUgdG8gZXhjbHVkZSAqKkNlbGwgY3ljbGUqKiwgKipyaWJvc29tYWwqKiBhbmQgKiptaXRvY2hvbmRyaWFsKiogYXNzb2NpYXRlZCBnZW5lcywgYXMgd2VsbCBhcyAqKlhpc3QqKiBmb3IgdGhlIGNsdXN0ZXJpbmcgc3RlcC4gV2UgYWxzbyByZXRhaW5lZCBnZW5lIGRldGVjdGVkIGZvciB3aGljaCB0cmFuc2NyaXB0cyBoYXZlIGJlZW4gZGV0ZWN0ZWQgaW4gYXQgbGVhc3QgMyBjZWxscwoKYGBge3J9CiMgRXhjbHVkZSBjZWxsIGN5Y2xlIGFzc29jaWF0ZWQgZ2VuZXMKQ0NnZW5lcyA8LSBhcy5jaGFyYWN0ZXIocmVhZC50YWJsZSgiLi9Qcm9nZW5pdG9ycy9DZWxsQ3ljbGVHZW5lcy5jc3YiLCBzZXAgPSAiXHQiLCBoZWFkZXIgPSBGKVssMV0pCiNFeGNsdWRlIGdlbmVzIGRldGVjdGVkIGluIGxlc3MgdGhhbiAzIGNlbGxzCm51bS5jZWxscyA8LSBNYXRyaXg6OnJvd1N1bXMoQVAuZGF0YUBkYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbd2hpY2goeCA9IG51bS5jZWxscyA+PSAzKV0pCgpHZW5lc1RvUmVtb3ZlIDwtIGMoZ3JlcChwYXR0ZXJuID0gIiheUnBsfF5ScHN8Xk1ycCkiLCB4ID0gZ2VuZXMudXNlLCB2YWx1ZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgZ3JlcChwYXR0ZXJuID0gIl5tdC0iLCB4ID0gZ2VuZXMudXNlLCB2YWx1ZSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgIlhpc3QiLCBDQ2dlbmVzKQoKZ2VuZXMudXNlIDwtIGdlbmVzLnVzZVshZ2VuZXMudXNlICVpbiUgR2VuZXNUb1JlbW92ZV0KYGBgCgojIyMjIE5vcm1hbGl6YXRpb24KYGBge3J9CmRnZU1hdHJpeF9jb3VudCA8LSBhcy5tYXRyaXgoQVAuZGF0YUByYXcuZGF0YSlbcm93bmFtZXMoQVAuZGF0YUByYXcuZGF0YSkgJWluJSBnZW5lcy51c2UsXQpkZ2VNYXRyaXhfY3BtIDwtIGNwbShkZ2VNYXRyaXhfY291bnQpCm5vcm0uZGF0IDwtIGxvZzIoZGdlTWF0cml4X2NwbSArIDEpCmBgYAoKYGBge3J9Cm5vcm0uZGF0IDwtIE1hdHJpeChub3JtLmRhdCwgc3BhcnNlID0gVFJVRSkKRGF0YS5tYXRyaXggPC0gbGlzdChyYXcuZGF0PWRnZU1hdHJpeF9jb3VudCwgbm9ybS5kYXQ9bm9ybS5kYXQpCmF0dGFjaChEYXRhLm1hdHJpeCkKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJBUC5kYXRhIiwgIkRhdGEubWF0cml4IildKQpgYGAKCiMjIyMgU2VsZWN0IGZlYXR1cmUgdXNlZCB0byByZW1vdmUgUENzIHdoaWNoIHdvdWxkIGNvcnJlbGF0ZSB3aXRoIHVud2FudGVkIHNvdXJjZSBvZiB2YXJpYXRpb25zIAoKYGBge3J9CiNEaW1lbnNpb24gRmlsdGVyaW5nCmdlbmUuY291bnRzIDwtIGxvZzIoY29sU3Vtcyhhcy5tYXRyaXgoRGF0YS5tYXRyaXgkbm9ybS5kYXQpID4gMCkpCm5VTUkgPC0gbG9nMihjb2xTdW1zKERhdGEubWF0cml4JHJhdy5kYXQpKQpwZXJjdE1pdG8gPC0gQVAuZGF0YUBtZXRhLmRhdGEkcGVyY2VudC5taXRvCnBlcmN0UmlibyA8LSBBUC5kYXRhQG1ldGEuZGF0YSRwZXJjZW50LnJpYm8KUHNldWRvRFZzY29yZSA8LSBBUC5kYXRhQG1ldGEuZGF0YSREb3Jzb1ZlbnRyYWwuU2NvcmUKCnJtLmVpZ2VuIDwtIGFzLm1hdHJpeChjYmluZChnZW5lLmNvdW50cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5VTUksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdE1pdG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjdFJpYm8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQc2V1ZG9EVnNjb3JlKSkKCnJvdy5uYW1lcyhybS5laWdlbikgPC0gbmFtZXMoZ2VuZS5jb3VudHMpCgpjb2xuYW1lcyhybS5laWdlbikgPC0gYygibG9nMm5HZW5lcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJsb2cyblVNSSIsCiAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjdE1pdG8iLAogICAgICAgICAgICAgICAgICAgICAgICAicGVyY3RSaWJvIiwKICAgICAgICAgICAgICAgICAgICAgICAgIlBzZXVkb0RWc2NvcmUiKQoKcm0oZ2VuZS5jb3VudHMsIG5VTUksIHBlcmN0TWl0bywgcGVyY3RSaWJvLFBzZXVkb0RWc2NvcmUpCmBgYAoKIyMjIEl0ZXJhdGl2ZSBjbHVzdGVyaW5nCgpgYGB7cn0KIyBTZXR0aW5nIFBhcmFtZXRlcnMgZm9yIGl0ZXJhdGl2ZSBjbHVzdGVyaW5nCmRlLnBhcmFtIDwtIGRlX3BhcmFtKHBhZGoudGggICAgID0gMC4wMSwgCiAgICAgICAgICAgICAgICAgICAgIGxmYy50aCAgICAgID0gMC45LAogICAgICAgICAgICAgICAgICAgICBsb3cudGggICAgICA9IDEsIAogICAgICAgICAgICAgICAgICAgICBxMS50aCAgICAgICA9IDAuMjUsIAogICAgICAgICAgICAgICAgICAgICBxMi50aCAgICAgICA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgIHEuZGlmZi50aCAgID0gMC43LAogICAgICAgICAgICAgICAgICAgICBkZS5zY29yZS50aCA9IDEwMCwKICAgICAgICAgICAgICAgICAgICAgbWluLmNlbGxzID0gMTApCmBgYAoKIyMjIyBSdW4gdGhlIGl0ZXJhdGl2ZSBjbHVzdGVyaW5nCgpUaGUgZGVmYXVsdCBpdGVyX2NsdXN0IGZ1bmN0aW9uIHVzZSBpbiB0aGlzIHZlcnNpb24gb2YgdGhlIHNjcmF0dGNoLmhpY2F0IHBhY2thZ2UgZG9lcyBub3QgYWxsb3cgdG8gc2V0IHRoZSBrLnBhcmFtIGFyZ3VtZW50LiBXZSBtb2RpZnkgdGhpcyBmdW5jdGlvbiB0byBhbGxvdyB0aGlzIGFyZ3VtZW50IHRvIGJlIHNldCB0byBvdGhlciB2YWx1ZXMuCgpgYGB7ciBjbGFzcy5vdXRwdXQ9InNjcm9sbC0xMDAifQojIFBlcmZvcm0gdGhlIGl0ZXJhdGl2ZSBjbHVzdGVyaW5nIAppdGVyLnJlc3VsdCA8LSBpdGVyX2NsdXN0KG5vcm0uZGF0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudHMgPSByYXcuZGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgIGRpbS5tZXRob2QgPSAicGNhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBtYXguZGltID0gMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGUucGFyYW0gPSBkZS5wYXJhbSwKICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gInVuZGlyZWN0aW9uYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJtLmVpZ2VuID0gcm0uZWlnZW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgay5wYXJhbSA9IDE1LAogICAgICAgICAgICAgICAgICAgICAgICAgIHJtLnRoID0gMC43LAogICAgICAgICAgICAgICAgICAgICAgICAgIHZnLnBhZGoudGggPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImxvdXZhaW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeCA9ICJ0ZXN0LWl0ZXJfY2x1c3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGKQoKYGBgCiMjIyMgTWVyZ2UgY2x1c3RlcnMgbm90IHNlcGVyYWJsZSBieSBERUdzCgpgYGB7cn0KIyBNZXJnZSBjbHVzdGVycyB3aGljaCBhcmUgbm90IHNlcGVyYWJsZSBieSBERUdzIGJlY2F1c2UgdGhleSB3b3VsZCBoYXZlIGJlZW4gc2VwYXJhdGVkIGF0IGEgZWFybHkgc3RlcCBvZiB0aGUgcHJvY2VzcwpyZC5kYXQgPC0gdChub3JtLmRhdFtpdGVyLnJlc3VsdCRtYXJrZXJzLF0pCm1lcmdlLnJlc3VsdCA8LSBtZXJnZV9jbChub3JtLmRhdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBjbCA9IGl0ZXIucmVzdWx0JGNsLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHJkLmRhdCA9IHJkLmRhdCwKICAgICAgICAgICAgICAgICAgICAgICAgIGRlLnBhcmFtID0gZGUucGFyYW0pCgpjYXQobGVuZ3RoKHVuaXF1ZShtZXJnZS5yZXN1bHQkY2wpKSwiIENsdXN0ZXJzXG4iKQpjYXQobGVuZ3RoKHVuaXF1ZShtZXJnZS5yZXN1bHQkbWFya2VycykpLCAiIERFIGdlbmVzIikKYGBgCgojIyMjIEltcG9ydCBjZWxsIGxhYmVscyBpbnRvIHRoZSBTZXVyYXQgb2JqCgpgYGB7ciBmaWcuZGltPWMoNS4zLCA0KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgZWxlbWVudCBGaWcuIDJDIn0KQVAuZGF0YUBpZGVudCA8LSBhcy5mYWN0b3IobWVyZ2UucmVzdWx0JGNsKQpBUC5kYXRhQG1ldGEuZGF0YSRQYWxsaWFsLnN1YkRvbWFpbmUgPC1hcy5jaGFyYWN0ZXIoQVAuZGF0YUBpZGVudCkKCmNvbG9ycyA8LSAgYygiIzk2OTY5NiIsICIjZTc4MjNhIikKCkRpbVBsb3QoQVAuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIHB0LnNpemUgPSAyLAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgY29scy51c2UgPSBjb2xvcnMpCmBgYAoKIyMgRmluZCBzdWItZG9tYWluIG1hcmtlciBnZW5lcwpgYGB7cn0KIyBGaW5kIGdlbmVzIHdoaWNoIGJlc3QgZGlzdGluZ3Vpc2ggdGhlIHN1YmRvbWFpbgpBbGxtYXJrZXJzIDwtIEZpbmRBbGxNYXJrZXJzKG9iamVjdCA9IEFQLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVzdC51c2UgPSAicm9jIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4ucGN0ID0gMC4zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2ZjLnRocmVzaG9sZCA9IDAuNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludC5iYXIgPSBULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ubHkucG9zID0gVCkKCkFsbG1hcmtlcnMkcS5kaWZmIDwtIGFicyhBbGxtYXJrZXJzJHBjdC4xIC0gQWxsbWFya2VycyRwY3QuMikvbWF4KEFsbG1hcmtlcnMkcGN0LjEsIEFsbG1hcmtlcnMkcGN0LjIpCkFsbG1hcmtlcnMkU3BlY2lmaWNpdHkuaW5kZXggPC0gQWxsbWFya2VycyRhdmdfbG9nRkMvICgxLUFsbG1hcmtlcnMkcS5kaWZmKQoKU2VsZWN0ZWQubWFya2VycyA8LSBBbGxtYXJrZXJzICU+JQogIGZpbHRlcihTcGVjaWZpY2l0eS5pbmRleCA+IDEpICU+JSBwdWxsKGdlbmUpCmBgYAoKYGBge3J9CiMgUHJlcGFyZSBhbm5vdGF0aW9uIGZvciBoaWNhdCBwaXBlbGluZQpjb2xvcnMgPC0gIGMoIiM5Njk2OTYiLCAiI2U3ODIzYSIpCmNvbG9yc2lkZW50IDwtIGNiaW5kKGlkZW50ID0gdW5pcXVlKGFzLmNoYXJhY3RlcihBUC5kYXRhQGlkZW50KSksCiAgICAgICAgICAgICAgICAgICAgIGNvbG9ycyA9IGNvbG9ycywKICAgICAgICAgICAgICAgICAgICAgaWQgPSB1bmlxdWUoYXMuY2hhcmFjdGVyKEFQLmRhdGFAaWRlbnQpKSkKCiNDcmVhdGUgYW5ub3RhdGlvbiBkYXRhLmZyYW1lCmFubm8uZGYgPC0gYXMuZGF0YS5mcmFtZShjYmluZCgKICBzYW1wbGVfbmFtZSA9IHJvdy5uYW1lcyhBUC5kYXRhQG1ldGEuZGF0YSksCiAgcHJpbWFyeV90eXBlX2lkID0gY29sb3JzaWRlbnRbbWF0Y2goYXMuY2hhcmFjdGVyKEFQLmRhdGFAaWRlbnQpLCBjb2xvcnNpZGVudFssMV0pLDNdLAogIHByaW1hcnlfdHlwZV9sYWJlbCA9IGFzLmNoYXJhY3RlcihBUC5kYXRhQGlkZW50KSwKICBwcmltYXJ5X3R5cGVfY29sb3IgPSBjb2xvcnNpZGVudFttYXRjaChhcy5jaGFyYWN0ZXIoQVAuZGF0YUBpZGVudCksIGNvbG9yc2lkZW50WywxXSksMl0KKSkKCgojUGxvdCBjZWxscyBiYXJwbG90CmRhdGEgPC0gY2JpbmQoc2FtcGxlX25hbWUgPSBjb2xuYW1lcyhBUC5kYXRhQGRhdGEpLAogICAgICAgICAgICAgIGFzLmRhdGEuZnJhbWUodChhcy5tYXRyaXgoQVAuZGF0YUBkYXRhKSkpKQoKc2FtcGxlX2Jhcl9wbG90KGRhdGEsIAogICAgICAgICAgICAgICAgYW5uby5kZiwgCiAgICAgICAgICAgICAgICBnZW5lcyA9IFNlbGVjdGVkLm1hcmtlcnMsCiAgICAgICAgICAgICAgICBncm91cF9vcmRlciA9IGMoIjEiLCIzIiksCiAgICAgICAgICAgICAgICBncm91cGluZyA9ICJwcmltYXJ5X3R5cGUiLAogICAgICAgICAgICAgICAgbG9nX3NjYWxlID0gRkFMU0UsCiAgICAgICAgICAgICAgICBmb250X3NpemUgPSA3LAogICAgICAgICAgICAgICAgbGFiZWxfaGVpZ2h0ID0gMTAsCiAgICAgICAgICAgICAgICBsYWJlbF90eXBlID0gImFuZ2xlIiwKICAgICAgICAgICAgICAgIGJnX2NvbG9yID0iI2Y3ZjdmNyIpCmBgYAoKCiMgU2Vzc2lvbiBJbmZvCmBgYHtyfQojZGF0ZQpmb3JtYXQoU3lzLnRpbWUoKSwgIiVkICVCLCAlWSwgJUgsJU0iKQoKI1BhY2thZ2VzIHVzZWQKc2Vzc2lvbkluZm8oKQpgYGA=